package cn.csc.module.pay.mq.listener;

import cn.csc.module.pay.dal.dataobject.jzborder.JzbOrderDO;
import cn.csc.module.pay.dal.mysql.jzborder.JzbOrderMapper;
import cn.csc.module.pay.dal.mysql.mqrecord.PayMqRecordMapper;
import cn.csc.module.pay.message.JzbOrderMessage;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 见证宝冻结充值消息事务监听器
 * rocketmq事务消息：https://rocketmq.apache.org/zh/docs/featureBehavior/04transactionmessage
 * 使用事务消息 https://blog.csdn.net/gsls200808/article/details/133278138
 * @author liuchuang
 * @version 1.0
 * @modify
 * @since 2025/1/2 9:28
 */
@Slf4j
@Component
public class JzbOrderMessageTransactionListener implements TransactionListener {

    @Resource
    private JzbOrderMapper jzbOrderMapper;
    @Resource
    private PayMqRecordMapper payMqRecordMapper;

    /**
     * 当事务半消息(prepare)发送成功后，此方法将被调用来执行本地事务
     * {@link JzbOrderMessage}
     * @param msg Half(prepare) message
     * @param arg Custom business parameter
     * @return Transaction state
     */
    @Override
    public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        log.info("executeLocalTransaction: {}",msg);
        // body为producer发送的message的payload
        log.info("executeLocalTransaction: body={}", new String(msg.getBody()));
        JSONObject msgBody = JSONObject.parseObject(new String(msg.getBody()));
        try {
            JzbOrderDO jzbOrderDO = jzbOrderMapper.selectById(msgBody.getBigInteger("id"));
            if (jzbOrderDO != null){
                payMqRecordMapper.updateByJzbOrderIdAndBusiType(jzbOrderDO.getId(), "1", "1", null);
                return LocalTransactionState.COMMIT_MESSAGE;
            }
            return LocalTransactionState.ROLLBACK_MESSAGE;
        } catch (Exception e){
            e.printStackTrace();
            return LocalTransactionState.UNKNOW;
        }
    }

    /**
     * When no response to prepare(half) message. broker will send check message to check the transaction status, and this
     * method will be invoked to get local transaction status.
     * 当事务半消息没有响应时，Broker将发送check消息来检查事务状态，并将调用此方法来获取本地事务状态
     *
     * @param msg Check message
     * @return Transaction state
     */
    @Override
    public LocalTransactionState checkLocalTransaction(MessageExt msg) {
        log.info("checkLocalTransaction: {}",msg);
        JSONObject msgBody = JSONObject.parseObject(new String(msg.getBody()));
        log.info("checkLocalTransaction JzbOrderMessage: {}", msgBody.toJSONString());
        try {
            JzbOrderDO jzbOrderDO = jzbOrderMapper.selectById(msgBody.getBigInteger("id"));
            if (jzbOrderDO != null){
                payMqRecordMapper.updateByJzbOrderIdAndBusiType(jzbOrderDO.getId(), "1", "1",null);
                return LocalTransactionState.COMMIT_MESSAGE;
            }
            return LocalTransactionState.ROLLBACK_MESSAGE;
        } catch (Exception e){
            e.printStackTrace();
            return LocalTransactionState.UNKNOW;
        }
    }
}
